package cz.proks.schoolpupilbook.gwt.widget.common;

import java.util.LinkedList;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

import cz.proks.schoolpupilbook.gwt.core.SchoolPupilBookFactory;
import cz.proks.schoolpupilbook.shared.domain.User;
import cz.proks.schoolpupilbook.shared.domain.User.Role;

public class UserForm extends Composite {

	private static ValidatingFormUiBinder uiBinder = GWT.create(ValidatingFormUiBinder.class);
	
	interface ValidatingFormUiBinder extends UiBinder<Widget, UserForm> {
	}
	
	@UiField Errors errors;
	@UiField Grid table;
	@UiField TextBox idBox;
	@UiField TextBox nameBox;
	@UiField TextBox surnameBox;
	@UiField TextBox loginBox;
	@UiField PasswordTextBox passwordBox;
	@UiField PasswordTextBox rePasswordBox;
	@UiField ListBox roleListBox;
	@UiField Button submitButton;
	@UiField Button backButton;

	public UserForm() {
		initWidget(uiBinder.createAndBindUi(this));		
	}
	
	public String getId() {
		return this.idBox.getValue();
	}
	
	public void setId(String id) {
		this.idBox.setValue(id);
	}	
	
	public String getName() {
		return this.nameBox.getValue();
	}
	
	public void setName(String name) {
		this.nameBox.setValue(name);
	}
	
	public String getSurname() {
		return this.surnameBox.getValue();
	}
	
	public void setSurname(String surname) {
		this.surnameBox.setValue(surname);
	}
	
	public String getLogin() {
		return this.loginBox.getValue();
	}
	
	public void setLogin(String login) {
		this.loginBox.setValue(login);
	}
	
	public String getPassword() {
		return this.passwordBox.getValue();
	}
	
	public void setPassword(String password) {
		this.passwordBox.setValue(password);
	}
	
	protected String getRePassword() {
		return this.rePasswordBox.getValue();
	}
	
	protected void setRePassword(String rePassword) {
		this.rePasswordBox.setValue(rePassword);
	}	
	
	public void setRoles(LinkedList<User.Role> roles) {
		roleListBox.clear();
		
		if (roles != null)			
			for (User.Role role : roles) {
				roleListBox.addItem(role.toString());
			}
	}
	
	public User.Role getRole() {
		int index = roleListBox.getSelectedIndex();
		return index < 0 ? null : User.Role.valueOf(roleListBox.getValue(index));
	}
	
	public void setRole(User.Role role) {
		int itemCount = roleListBox.getItemCount();
		String roleStr = role.toString();
		
		for (int i = 0; i < itemCount; i++) {
			if (roleStr.equals(roleListBox.getValue(i))) {
				roleListBox.setSelectedIndex(i);
				break;
			}					
		}
	}
	
	public boolean isIdReadOnly() {
		return idBox.isReadOnly();
	}
	
	public void setIdReadOnly(boolean value) {
		idBox.setReadOnly(value);
	}
	
	public boolean isNameReadOnly() {
		return nameBox.isReadOnly();
	}
	
	public void setNameReadOnly(boolean value) {
		nameBox.setReadOnly(value);
	}
	
	public boolean isSurnameReadOnly() {
		return surnameBox.isReadOnly();		
	}
	
	public void setSurnameReadOnly(boolean value) {
		surnameBox.setReadOnly(value);
	}
	
	public boolean isLoginReadOnly() {
		return loginBox.isReadOnly();
	}
	
	public void setLoginReadOnly(boolean value) {
		loginBox.setReadOnly(value);
	}
	
	public boolean isPasswordReadOnly() {
		return passwordBox.isReadOnly();
	}
	
	public void setPasswordReadOnly(boolean value) {
		passwordBox.setReadOnly(value);
		rePasswordBox.setReadOnly(value);
	}
	
	public boolean isRolesReadOnly() {
		return roleListBox.isEnabled();
	}
	
	public void setRolesReadOnly(boolean value) {
		roleListBox.setEnabled(value);
	}
	
	@UiHandler("submitButton")
	public void submit(ClickEvent event) {
		LinkedList<String> errors = validate();
		if (errors.isEmpty()) {
			this.errors.setErrors(null);
			SubmitEvent submitEevent = new SubmitEvent(getId(), getName(), getSurname(), getLogin(), getPassword(), getRole());
			SchoolPupilBookFactory.getEventBus().fireEvent(submitEevent);		
		} else {
			this.errors.setErrors(errors);			
		}
	}
	
	@UiHandler("backButton")
	public void back(ClickEvent event) {
		History.back();
	}
		
	private LinkedList<String> validate() {
		LinkedList<String> errors = new LinkedList<String>();
		
		if (getName() == null || getName().isEmpty())
			errors.add("Name field is empty");
		
		if (getSurname() == null || getSurname().isEmpty())
			errors.add("Surname field is empty");
		
		if (getLogin() == null || getLogin().isEmpty())
			errors.add("Login field is empty");
		
		if (getPassword() == null || getPassword().isEmpty())			
			errors.add("Password field is empty");
		
		if (getRePassword() == null || getRePassword().isEmpty() || !getRePassword().equals(getPassword()))
			errors.add("Password re-type doesn't match password");
		
		if (getRole() == null)
			errors.add("No role selected");
		
		return errors;
	}
	
	public static class SubmitEvent extends GwtEvent<SubmitEvent.SubmitEventHandler> {
		public interface SubmitEventHandler extends EventHandler {
			void onSubmit(SubmitEvent event);
		}
		
		public final static Type<SubmitEvent.SubmitEventHandler> TYPE = new Type<SubmitEvent.SubmitEventHandler>();
		
		private String id;
		private String name;
		private String surname;
		private String username;
		private String password;
		private User.Role role;
		
		public SubmitEvent(String id, String name, String surname,
				String username, String password, Role role) {
			super();
			this.id = id;
			this.name = name;
			this.surname = surname;
			this.username = username;
			this.password = password;
			this.role = role;
		}
		
		@Override
		public Type<SubmitEventHandler> getAssociatedType() {
			return TYPE;
		}
		
		@Override
		protected void dispatch(SubmitEventHandler handler) {
			handler.onSubmit(this);			
		}
		
		public String getId() {
			return id;
		}

		public String getName() {
			return name;
		}

		public String getSurname() {
			return surname;
		}

		public String getUsername() {
			return username;
		}

		public String getPassword() {
			return password;
		}

		public User.Role getRole() {
			return role;
		}		
	}
}
